﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.IO;

namespace IETTortak
{
    public class AsyncServiceParser
    {
        private const int numberOfThreadsToUse = 4;
        private List<string> dosyalar;
        private Semaphore semaParse = new Semaphore(numberOfThreadsToUse, numberOfThreadsToUse);
        private const int DosyaPerThread = 100;


        public delegate void ALVHataHandler(string key, string message);
        public delegate void ALVDurumDeğiştiHandler(string key);
        public delegate void ALVEkle(string key, string message);
        public delegate void ServiceEkleHandler(Service g);
        public event ALVDurumDeğiştiHandler Processing;
        public event ALVDurumDeğiştiHandler Success;
        public event ALVHataHandler Hata;
        public delegate void ServicelerTarandıHandler();

        public event ServicelerTarandıHandler ServicelerTarandı;
        public event ALVEkle Ekle;
        public event ServiceEkleHandler ServiceEkle;

        public delegate void UpdateProgressHandler(string key, int tamamlanan, int tümü);
        public event UpdateProgressHandler UpdateProgress;


        public int ServiceCount
        {
            get { return dosyalar.Count; }
        }

        protected void OnUpdateProgress(string key, int tamamlanan, int tümü)
        {
            if (UpdateProgress != null)
                UpdateProgress(key, tamamlanan, tümü);
        }

        protected void OnServislerTarandı()
        {
            if (ServicelerTarandı != null)
                ServicelerTarandı();
        }

        protected void OnServiceEkle(Service g)
        {
            if (ServiceEkle != null)
                ServiceEkle(g);
        }

        protected void OnProcessing(string key)
        {
            if (Processing != null)
                Processing(key);
        }

        protected void OnSuccess(string key)
        {
            if (Success != null)
                Success(key);
        }

        protected void OnHata(string key, string message)
        {
            if (Hata != null)
                Hata(key, message);
        }

        protected void OnEkle(string key, string message)
        {
            if (Ekle != null)
                Ekle(key, message);
        }


        public AsyncServiceParser(string[] servisDosyaları)
        {
            dosyalar = new List<string>(servisDosyaları);
        }

        public void Start()
        {
            Thread t = new Thread(new ThreadStart(StartProcessing));
            t.Start();
        }

        private void StartProcessing()
        {
            while (dosyalar.Count > 0)
            {
                List<string> dosyalarToProcess = dosyalar.GetRange(0, Math.Min(DosyaPerThread, dosyalar.Count));
                dosyalar.RemoveRange(0, Math.Min(DosyaPerThread, dosyalar.Count));

                semaParse.WaitOne();

                ThreadPool.QueueUserWorkItem(new WaitCallback(Dosyalarıİşle), dosyalarToProcess);
            }

            for (int ctr = 0; ctr < numberOfThreadsToUse; ctr++)
            {
                semaParse.WaitOne();
            }
            semaParse.Release(numberOfThreadsToUse);
            OnServislerTarandı();
        }

        private void Dosyalarıİşle(object state)
        {
            string key = Guid.NewGuid().ToString();
            try
            {
                List<string> işlenecekDosyalar = state as List<string>;
                OnEkle(key, string.Format("Taranan dosya sayısı: {0} - ThreadID: ", işlenecekDosyalar.Count) + Thread.CurrentThread.ManagedThreadId.ToString());
                OnProcessing(key);
                int tamamlanan = 0;
                foreach (string s in işlenecekDosyalar)
                {
                    OnServiceEkle(ServiceParser.Parse(Path.GetFileNameWithoutExtension(s), File.ReadAllText(s)));
                    tamamlanan++;
                    OnUpdateProgress(key, tamamlanan, işlenecekDosyalar.Count);
                }
                OnSuccess(key);
            }
            catch (Exception ex)
            {
                OnHata(key, ex.Message);
            }
            finally
            {
                semaParse.Release();
            }
        }
    }
}
